
/**
 * @author Daniel Weber
 * Statische Klasse, die für die komplette Spielsteuerung zuständig ist.
 */
import java.io.IOException;
import javax.microedition.lcdui.Graphics;
import javax.microedition.midlet.MIDlet;

public class Game {

    //Array der Figuren
    public static GMan[] gMan;
    //Lvelinstanz
    public static level lvl;
    //Spielsteuernde Variablen
    public static int iGameSpeed = 6, iSpielerZahl = 1, iFrontMan = 0, iHighscore = 0;
    //temporäre Highscoreliste
    public static int[] higscoreListe, spielerPunkte = {0, 0, 0, 0};
    //ob das Menü geöffnet ist
    public static boolean bMenu = false, bChoice = false;
    //Zeigt Spielerbelegung
    public static boolean[] bPlayer = new boolean[4];
    //Instanz vom Muskspieler
    public static MusicPlayer player;
    //Spielzustände
    public static final int PLAY = 0;
    public static final int INTRO_SCREEN = 1;
    public static final int GAMEOVER_SCREEN = 2;
    public static final int MENU = 3;
    public static int[] state = {INTRO_SCREEN};
    public static int playtimer = 0;

    /**
     * Initialisiert eine neue Runde des Spiels.
     */
    public static void Init() {
        gMan = new GMan[4];
        for (int i = 0; i < 4; i++) {
            gMan[i] = new GMan(i);
            gMan[i].setVisible(bPlayer[i]);
        }
        lvl = new level();
        iGameSpeed = 6;
        iHighscore = 0;
    }

    /**
     * Standard Schleife, die jedes Frame ausgeführt wird.
     */
    public static void loop(MIDlet PG, Graphics g) throws IOException {
        switch (state[0]) {
            case PLAY:
                play(PG, g);
                break;
            case INTRO_SCREEN:
                intro(PG, g);
                break;
            case GAMEOVER_SCREEN:
                gameover(PG, g);
                break;
        }
    }

    /**
     * Die laufende Spielschleife.
     */
    private static void play(MIDlet PG, Graphics g) throws IOException {
        if (ActionCanvas.bGameD && iSpielerZahl == 1 && !bChoice
                || (ActionCanvas.bLeft || ActionCanvas.bRight) && iSpielerZahl > 1) {
            bMenu = !bMenu;
            ActionCanvas.clearButtons();
        }
        if (bMenu) {
            system.drawParallaxBackground(g);
            lvl.paint(g, 0, 0);
            system.drawMenu(g, true);
        } else if (iSpielerZahl == 1) {
            system.drawParallaxBackground(g);
            playtimer++;
            system.pumpTimer();//Timer laufen lassen
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Bewegen~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            gMan[0].nextFrame();
            movement(iGameSpeed);//die Figuren bewegen
            handleInput();//reagiert auf die Eingabe
            moveScreen();//den Bildschirm ausrichten
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Zeichnen~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            lvl.paint(g, 0, 0);
            system.drawFPS(g);//Performance anzeigen
            system.quickText("" + iHighscore, system.w - system.fontH - 2, system.h * 3 / 4, g);//highscore anzeigen
            if (gMan[iFrontMan].getY() >= level.newMapLayer.getY() + level.newMapLayer.getHeight() - system.h * 3 / 2) {//Beim erreichen von der hälfte des Levels neues schon laden
                lvl.Levelaufbau();
                if (lvl.stufe % 3 == 0) {
                    iGameSpeed++;
                }
            }
            if (!gMan[0].isOnScreen()) {
                setHighscore();
                state[0] = GAMEOVER_SCREEN;
            }
        } else {
            system.drawParallaxBackground(g);
            playtimer++;
            system.pumpTimer();//Timer laufen lassen
            movement(iGameSpeed);//die Figuren bewegen
            handleInput();//reagiert auf die Eingabe
            moveScreen();//den Bildschirm ausrichten
            lvl.paint(g, 0, 0);
            if (gMan[iFrontMan].getY() >= level.newMapLayer.getY() + level.newMapLayer.getHeight() - system.h * 3 / 2) {//Beim erreichen von der hälfte des Levels neues schon laden
                lvl.Levelaufbau();
                if (lvl.stufe % 3 == 0) {
                    iGameSpeed++;
                }
            }
//GMans die aus dem bild verschwinden, verschwinden für immer
            for (int i = 0; i < 4; i++) {
                gMan[i].nextFrame();
                if (!gMan[i].isOnScreen()) {
                    gMan[i].setVisible(false);
                }
            }
//zählt die noch aktiven GMans
            int n = 0;
            for (int m = 0; m < 4; m++) {
                if (gMan[m].isVisible()) {
                    n++;
                }
            }
            if (n <= 1) {
                for (int m = 0; m < 4; m++) {
                    if (gMan[m].isVisible()) {
                        spielerPunkte[m]++;
                        break;
                    }
                }

                state[0] = GAMEOVER_SCREEN;
            }

        }
        if (player == null) {
            player = new MusicPlayer();
        } else if (player.fertig()) {
            player = new MusicPlayer();
        }
    }

    /**
     * Wird zu Beginn ausgeführt, bis das Menü beendet wird.
     */
    private static void intro(MIDlet PG, Graphics g) {
        if (ActionCanvas.bAnyKey && !bMenu) {
            bMenu = true;
            ActionCanvas.clearButtons();
        }
        system.clearScreen(0x00000000, g);
        g.drawImage(system.img[system.splashScreenJPG], 0, 0, system.anchor);
        if (!bMenu) {
            g.setColor(0x00ffffff);
            g.setFont(system.font);
            g.drawString("Bitte eine Taste drücken", system.w / 2 - system.font.stringWidth("Bitte eine Taste drücken") / 2, system.h * 2 / 3, system.anchor);
        } else {
            system.drawMenu(g, false);
        }
    }

    /**
     * Wird beim Ende jeder Runde ausgeführt.
     * Setzt Punkte im Spiel.
     */
    private static void gameover(MIDlet PG, Graphics g) {
        if (ActionCanvas.bAnyKey) {
            state[0] = PLAY;
            ActionCanvas.clearButtons();
            Init();
        } else if (iSpielerZahl == 1) {
            system.clearScreen(0x00000000, g);
            int x = system.w * (7) / 10;
            int y = system.h / 3;
            for (int i = 0; i < higscoreListe.length; i++) {
                system.quickText((i + 1) + ".", x - 16 * i, y, g);
                if (iHighscore == higscoreListe[i]) {
                    system.quickText(">>" + higscoreListe[i], x - 16 * i, y + system.h / 3 - (">>" + String.valueOf(higscoreListe[i])).length() * system.fontH, g);
                } else {
                    system.quickText("" + higscoreListe[i], x - 16 * i, y + system.h / 3 - String.valueOf(higscoreListe[i]).length() * system.fontH, g);
                }
            }
        } else {
            system.clearScreen(0x00000000, g);
            int x = system.w * (7) / 10;
            int y = system.h / 3;
            for (int i = 0; i < 4; i++) {
                if (bPlayer[i]) {
                    gMan[i].setVisible(true);
                    gMan[i].setPosition(x - i * 40, y);
                    if (gMan[i].gravity == 1) {
                        gMan[i].switchGravity();
                    }
                    gMan[i].setFrame(1);
                    gMan[i].paint(g);
                    system.quickText("Siege: " + spielerPunkte[i], x - i * 40, y + 30, g);
                }
            }
        }
    }

    /**
     * Fügt die aktuelle Highscore in die temporäre Liste,absteigend geordnet, ein.
     */
    private static void setHighscore() {
        int value1 = iHighscore, value2 = 0;
        for (int i = 0; i < higscoreListe.length; i++) {
            if (value1 >= higscoreListe[i]) {
                value2 = higscoreListe[i];
                higscoreListe[i] = value1;
                value1 = value2;
            }
        }
    }

    /**
     * Bewegt die Figuren und überprüft Kollisionen.
     */
    private static void movement(int speed) {
        if (iSpielerZahl == 1) {
            for (int i = 0; i < speed; i++) {
                gMan[0].move(0, 1);
                iHighscore++;
                if (gMan[0].collidesWithLevel()) {
                    gMan[0].move(0, -1);
                    gMan[0].bCollide = true;//läuft er gegen einen Block wird es vermerkt
                    iHighscore--;
                } else {
                    gMan[0].bCollide = false;
                }
                gMan[0].move(gMan[0].gravity, 0);
                if (gMan[0].collidesWithLevel()) {
                    gMan[0].move(-gMan[0].gravity, 0);
                }
            }
            iFrontMan = 0;
        } else {
            for (int i = 0; i < speed; i++) {
                for (int n = 0; n < 4; n++) {
                    if (bPlayer[n]) {
                        gMan[n].move(0, 1);
                        if (gMan[n].collidesWithLevel() || gMan[n].collidesWithSprites()) {
                            gMan[n].move(0, -1);
                            gMan[n].bCollide = true;//läuft er gegen einen Block wird es vermerkt
                        } else {
                            gMan[n].bCollide = false;
                        }
                        gMan[n].move(gMan[n].gravity, 0);
                        if (gMan[n].collidesWithLevel() || gMan[n].collidesWithSprites()) {
                            gMan[n].move(-gMan[n].gravity, 0);
                        }

                    }
                    if (gMan[n].getY() > gMan[iFrontMan].getY() && gMan[n].isVisible()) {
                        iFrontMan = n;
                    }
                }
            }

            for (int i = 0; i < 4; i++) {
                if (gMan[i].getY() + 60 < gMan[iFrontMan].getY() && system.intervall(20 * iGameSpeed)) {
                    gMan[i].move(0, 1);
                    if (gMan[i].collidesWithLevel() || gMan[i].collidesWithSprites()) {
                        gMan[i].move(0, -1);
                    }
                }
            }
        }
    }

    /**
     * Prüft und führt Eingaben im Spiel aus.
     */
    private static void handleInput() {
        if (iSpielerZahl == 1) {
            gMan[0].move(gMan[0].gravity, 0);
            if (gMan[0].collidesWithLevel() && ActionCanvas.bFire) {
                gMan[0].switchGravity();
                ActionCanvas.bFire = false;
            } else {
                gMan[0].move(-gMan[0].gravity, 0);
            }
        } else {
            for (int i = 0; i < 4; i++) {
                boolean var = (i == 0 && ActionCanvas.bGameA
                        || i == 1 && ActionCanvas.bGameB
                        || i == 2 && ActionCanvas.bGameC
                        || i == 3 && ActionCanvas.bGameD);
                gMan[i].move(gMan[i].gravity, 0);
                if ((gMan[i].collidesWithLevel() || gMan[i].collidesWithSprites()) && var) {
                    gMan[i].switchGravity();
                    if (i == 0) {
                        ActionCanvas.bGameA = false;
                    } else if (i == 1) {
                        ActionCanvas.bGameB = false;
                    } else if (i == 2) {
                        ActionCanvas.bGameC = false;
                    } else if (i == 3) {
                        ActionCanvas.bGameD = false;
                    }
                } else {
                    gMan[i].move(-gMan[i].gravity, 0);
                }
            }
        }
    }

    /**
     * Richtet die Kamera korrekt aus.
     */
    private static void moveScreen() {
        if (iSpielerZahl <= 1) {
            if (gMan[iFrontMan].bCollide) {
                level.position += iGameSpeed / 2;
            } else {
                if (system.getXLayer(gMan[iFrontMan]) < level.position && system.intervall(40 * iGameSpeed)) {
                    level.position--;//die figur holt langsam wieder auf
                }
                level.position += iGameSpeed;//der bildschirm läuft ohne kollision so schnell wie die figur
            }
            lvl.setViewWindow(0, level.position, system.w, system.h);
        } else {
            if (gMan[iFrontMan].bCollide) {
                level.position += iGameSpeed / 3;
            } else {
                if (system.getXLayer(gMan[iFrontMan]) < level.position && system.intervall(50 * iGameSpeed)) {
                    level.position--;//die figur holt langsam wieder auf
                }
                level.position += iGameSpeed;//der bildschirm läuft ohne kollision so schnell wie die figur
            }
            lvl.setViewWindow(0, level.position, system.w, system.h);
        }
    }
}
